/**
 * 
 */

package com.tenentia.pcmps.swm.util.pdf;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

import org.apache.log4j.Logger;

/**
 * 
 * @author tEnEntia, S.L.N.E.
 * 
 */
public class PDFGeneratorClassLoader extends ClassLoader {

	private static final Logger LOGGER = Logger.getLogger(PDFGeneratorClassLoader.class.getPackage().getName());

	byte[] jarBytes = null;

	/**
	 * @param parent
	 */
	PDFGeneratorClassLoader(byte[] jarBytes, ClassLoader parent) {

		super(parent);

		this.jarBytes = jarBytes;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.ClassLoader#loadClass(java.lang.String)
	 */
	@Override
	public Class<?> loadClass(String className) throws ClassNotFoundException {

		Class<?> methodResult = null;

		try {
			methodResult = super.loadClass(className);
		} catch (Exception e1) {

			ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(jarBytes);
			ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
			JarInputStream jarInputStream = null;
			JarEntry jarEntry = null;

			try {
				jarInputStream = new JarInputStream(byteArrayInputStream);
				String entryNameToMatch = className.replaceAll("\\.", "/").concat(".class");
				while ((jarEntry = jarInputStream.getNextJarEntry()) != null) {
					if (!jarEntry.isDirectory()) {
						if (jarEntry.getName().equals(entryNameToMatch)) {
							int readedByte = -1;
							while ((readedByte = jarInputStream.read()) != -1) {
								byteArrayOutputStream.write(readedByte);
							}
							byteArrayOutputStream.flush();
							byteArrayOutputStream.close();
						}
					}
				}
				byte[] entryBytes = byteArrayOutputStream.toByteArray();
				methodResult = defineClass(className, entryBytes, 0, entryBytes.length);
			} catch (Exception e2) {
				LOGGER.error(e2, e2);
			} finally {
				if (null != byteArrayInputStream) {
					try {
						byteArrayInputStream.close();
					} catch (Exception e) {
						// TODO: handle exception
					}
				}
				if (null != jarInputStream) {
					try {
						jarInputStream.close();
					} catch (Exception e) {
						// TODO: handle exception
					}
				}
			}
		}

		return methodResult;
	}

	@Override
	public InputStream getResourceAsStream(String name) {

		InputStream methodResult = null;

		methodResult = super.getResourceAsStream(name);

		if (null == methodResult) {

			ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(jarBytes);
			ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
			JarInputStream jarInputStream = null;
			JarEntry jarEntry = null;

			try {
				jarInputStream = new JarInputStream(byteArrayInputStream);
				while ((jarEntry = jarInputStream.getNextJarEntry()) != null) {
					if (!jarEntry.isDirectory()) {
						if (jarEntry.getName().equals(name)) {
							int readedByte = -1;
							while ((readedByte = jarInputStream.read()) != -1) {
								byteArrayOutputStream.write(readedByte);
							}
							byteArrayOutputStream.flush();
							byteArrayOutputStream.close();
						}
					}
				}
				byte[] entryBytes = byteArrayOutputStream.toByteArray();
				methodResult = new ByteArrayInputStream(entryBytes);
			} catch (Exception e2) {
				LOGGER.error(e2, e2);
			} finally {
				if (null != byteArrayInputStream) {
					try {
						byteArrayInputStream.close();
					} catch (Exception e) {
						// TODO: handle exception
					}
				}
				if (null != jarInputStream) {
					try {
						jarInputStream.close();
					} catch (Exception e) {
						// TODO: handle exception
					}
				}
			}
		}

		return methodResult;
	}

}
